#include<pthread.h>
//单例模式最大的三个特征
//一是构造函数私有化、禁止使用拷贝构造和赋值构造。
//二是实现单例对象静态存储、并且类型是类类型。
//三是需要提供一个静态获取方法来获取单例对象，确保整个程序中只有一个地方可以获取该类的实例。
namespace hungry
{
    template<class T> 
    class Sigleton
    {
    private:
        Sigleton()//构造函数私有化
        {}

    public:
        static Sigleton<T>* get_instance()//提供一个静态获取方法来获取单例对象，确保整个程序中只有一个地方可以获取该类的实例。
        {
            return &_instance;
        }
    private:
        static Sigleton<T> instance = new Sigleton();//实现单例对象静态存储、并且类型是类类型
    };
} // namespace hungry

namespace lazy
{
    template<class T> 
    class Sigleton
    {
    private:
        Sigleton()//构造函数私有化
        {}

    public:
        static Sigleton<T>* get_instance()
        {
            if(_instance == nullptr)
            {
            // 双重判定空指针, 降低锁冲突的概率, 提高性能. 
            // 使用互斥锁, 保证多线程情况下也只调用一次 new.
                pthread_mutex_lock(&lock);
                if(_instance == nullptr)
                {
                    _instance = new Sigleton<T>();
                }
                pthread_mutex_unlock(&lock);
            }

            return _instance;
        }
    private:
        volatile static Sigleton<T>* _instance;// 需要设置 volatile 关键字, 否则可能被编译器优化.
        static pthread_mutex_t _lock;
    };

    //静态变量必须在类外初始化
    template<class T>
    Sigleton<T>* Sigleton<T>::_instance = nullptr;
    template<class T>
    pthread_mutex_t Sigleton<T>::_lock = PTHREAD_MUTEX_INITIALIZER;

} 